<?php

namespace common\logic;

use common\LogicException;
use component\system\system_auth\SystemAuthModel;
use think\Exception;
use think\exception\ValidateException;
use think\facade\Db;
use think\Model;

/**
 * 这里使用了抽象类,在子类中必须实现 model 方法
 * Class MainLogic
 * @package app\common\logic
 */
abstract class Logic
{
    /**
     * @param
     * @return Model
     */
    abstract protected function model();

    /**
     * @var bool
     */
    public $fields = true;

    /**
     * @var array
     */
    public $order = ['id', 'desc'];

    /**
     * @var bool
     */
    public $onlyTrashed = false;

    /**
     * @var string
     */
    protected $validate = '';

    /**
     * @var array
     */
    protected $pages = [];

    /**
     * 获取实例
     * @return static
     */
    public static function instance()
    {
        return new static();
    }

    /**
     * @param null $params
     * @return Model
     */
    protected function query($params = null)
    {
        $model = $this->model();

        if ($this->onlyTrashed) {
            $model = $model::onlyTrashed();
        }

        if (is_array($params)) {
            $model = $model->where($params);
        }

        $model = $model->field($this->fields);
        $model = $model->order($this->order[0], $this->order[1]);

        return $model;
    }

    /**
     * 设置验证类
     * @param string $validate
     * @return $this
     */
    public function setValidate(string $validate)
    {
        if ($validate) {
            $this->validate = $validate;
        }

        return $this;
    }

    /**
     * 设置字段信息
     * @param array $fields
     * @return $this
     */
    public function setFields(array $fields)
    {
        $this->fields = $fields;

        return $this;
    }

    /**
     * @param $param
     * @return array|Model|null
     */
    public function find($param)
    {
        $record = null;

        try {

            $model = $this->model();

            if ($this->onlyTrashed) {
                $model = $model::onlyTrashed();
            }

            $model = $model->field($this->fields);

            if (is_array($param)) {
                $record = $model->where($param)->find();
            } else {
                $record = $model->find($param);
            }

        } catch (Exception $exception) {
            LogicException::instance()->exception($exception);
        }

        return $record;
    }

    /**
     * @param null $params
     * @return array|\think\Collection|\think\Paginator
     */
    public function select($params = null)
    {
        $records = null;

        try {

            if (request()->param('page')) {

                $page_size = request()->param('page_size', 15);

                $records = $this->query($params)->paginate($page_size);

            } else {
                $records = $this->query($params)->select();

                if ($records->isEmpty()) {
                    $records = null;
                }
            }

        } catch (Exception $exception) {
            LogicException::instance()->exception($exception);
        }

        return $records ? $records : null;
    }

    /**
     * @param $fields
     * @param string $key
     * @param null $params
     * @return array
     */
    public function column($fields, $key = 'id', $params = null)
    {
        $model = $this->model();

        if ($params) {
            $model = $model->where($params);
        }

        $records = $model->column($fields, $key);

        return $records;
    }

    /**
     * @param $data
     * @param null $scene 验证场景
     * @return bool|mixed|string
     */
    public function save($data, $scene = null)
    {
        $primary = $data['id'] ?? '';
        if ($this->validate) {
            try {
                if ($scene) {
                    validate($this->validate)->scene($scene)->check($data);
                } elseif (empty($primary)) {
                    validate($this->validate)->check($data);
                }
            } catch (ValidateException $exception) {
                LogicException::instance()->exception($exception);
                return false;
            }
        }

        if ($primary) {
            $record = $this->find($primary);
            $result = $record->save($data);
            return $result === false ? false : $primary;
        } else {
            $model = $this->model();
            $result = $model->save($data);
            if ($result) {
                return $model->id;
            }
            return false;
        }
    }

    /**
     * @param $data
     * @return bool|\think\Collection
     */
    public function saveAll($data)
    {
        $result = false;
        try {
            $result = $this->model()->saveAll($data);
        } catch (\Exception $exception) {
            LogicException::instance()->exception($exception);
        }

        return $result;
    }

    /**
     * 删除数据
     * @param $pk
     * @param $force
     * @return mixed
     */
    public function delete($pk, $force)
    {
        $force = boolval($force);

        if ($force) {
            $result = call_user_func_array([$this->model(), 'destroy'], [$pk, $force]);
        } else {
            $result = call_user_func_array([$this->model(), 'destroy'], [$pk]);
        }

        return $result;
    }

    /**
     * @param $pk
     * @return bool|int
     */
    public function recovery($pk)
    {
        $result = false;
        try {
            $result = Db::table($this->model()->getTable())->where('id', 'in', $pk)->update(
                [
                    'delete_time' => 0
                ]
            );
        } catch (Exception $exception) {
            LogicException::instance()->exception($exception);
        }

        return $result ? true : false;
    }
}